import { put,putParams } from '../src/oss-upload'; // 替换为实际的模块路径
import * as OSS from 'ali-oss';
import * as sinon from 'sinon';
import * as step from '@flow-step/step-toolkit'
import {UploadInputs} from '../src/upload-inputs'
import {expect} from 'chai'

describe('put', () => {
    const mockArtifact = {
        artifactName: 'testArtifact',
        artifactFullName: 'testArtifact.txt',
        fileMD5: 'testMD5',
        artifact: 'testArtifact',
        uploadType: 'testType',
        repoId: 'testRepoId',
        artifactVersion: '1.0.0',
        fileId: 'testFileId',
        accessKeyId: 'testAccessKeyId',
        accessKeySecret: 'testAccessKeySecret',
        bucketName: 'testBucketName',
        token: 'testToken'
    } as UploadInputs;

    let sandbox: sinon.SinonSandbox;

    beforeEach(() => {
        sandbox = sinon.createSandbox();
        process.env['ENDPOINT'] = 'testEndpoint';
        process.env['ARTIFACT_URL'] = 'testArtifactUrl';
        process.env['stepIdentifier'] = 'testStepIdentifier';
        process.env['FLOW_RUNNER_OSS_UPLOAD_TIMEOUT'] = '10000';
    });

    afterEach(() => {
        sandbox.restore();
        delete process.env['ENDPOINT'];
        delete process.env['ARTIFACT_URL'];
        delete process.env['stepIdentifier'];
        delete process.env['FLOW_RUNNER_OSS_UPLOAD_TIMEOUT'];
    });



    it('should upload has error and set outputs', async () => {
        const mockOSSClient = {
            put: sandbox.stub().resolves({ url: 'testUrl' })
        };

        sandbox.stub(step, 'oss').value({
            getEndpoint: sandbox.stub().resolves('testEndpoint')
        });
        try {
            await put(mockArtifact);
            expect.fail('Expected an error to be thrown');

        }catch (error){

            // @ts-ignore
            expect(error.message).to.contain('The bucket must be conform to the specifications');

        }

    });


});


describe('putParams', () => {
    let addOutputStub: sinon.SinonStub;
    let infoStub: sinon.SinonStub;
    let envBackup: NodeJS.ProcessEnv;

    beforeEach(() => {
        // Backup the original process.env
        envBackup = process.env;

        // Create a new process.env object
        process.env = {
            ARTIFACT_URL: 'http://example.com/artifact',
            stepIdentifier: 'step1'
        };

        // Stub the step.addOutput and step.info methods
        addOutputStub = sinon.stub(step, 'addOutput');
        infoStub = sinon.stub(step, 'info');
    });

    afterEach(() => {
        // Restore the original process.env
        process.env = envBackup;

        // Restore the stubs
        addOutputStub.restore();
        infoStub.restore();
    });

    it('should correctly format output strings with valid inputs', () => {
        const artifact = {
            bucketName: 'my-bucket',
            fileId: 'file1',
            artifactName: 'artifact1',
            fileMD5: 'md5hash',
            artifact: 'artifact1',
            uploadType: 'type1',
            repoId: 'repo1',
            fileParentId: 'parent1',
            artifactVersion: '1.0'
        } as UploadInputs;
        const result = {
            url: 'http://example.com/result'
        } as OSS.PutObjectResult;

        putParams(artifact, result);

        expect(addOutputStub.callCount).to.equal(3);
        expect(addOutputStub.firstCall.args[0]).to.equal('step1.ARTIFACT={"ARTIFACT_URL":"http://example.com/artifact","ARTIFACT_NAME":"artifact1","ARTIFACT_MD5":"md5hash","WEB_DOWNLOAD_URL":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact1","artifact":"artifact1","type":"flowPublic","downloadUrl":"http://example.com/result","md5":"md5hash"}');
        expect(addOutputStub.secondCall.args[0]).to.equal('PACKAGE_INFO={"packageLabel":"artifact1","packagePath":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact1","uploadType":"type1","repoId":"repo1"}');

        expect(infoStub.callCount).to.equal(1);
        expect(infoStub.firstCall.args[0]).to.equal('Artifact download URL is: http://example.com/result');
    });

    it('should handle missing ARTIFACT_URL environment variable', () => {
        delete process.env.ARTIFACT_URL;

        const artifact = {
            bucketName: 'my-bucket',
            fileId: 'file1',
            artifactName: 'artifact1',
            fileMD5: 'md5hash',
            artifact: 'artifact1',
            uploadType: 'type1',
            repoId: 'repo1',
            fileParentId: 'parent1',
            artifactVersion: '1.0'
        } as UploadInputs;
        const result = {
            url: 'http://example.com/result'
        } as OSS.PutObjectResult;

        putParams(artifact, result);

        expect(addOutputStub.callCount).to.equal(3);
        expect(addOutputStub.firstCall.args[0]).to.equal('step1.ARTIFACT={"ARTIFACT_URL":"undefined","ARTIFACT_NAME":"artifact1","ARTIFACT_MD5":"md5hash","WEB_DOWNLOAD_URL":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact1","artifact":"artifact1","type":"flowPublic","downloadUrl":"http://example.com/result","md5":"md5hash"}');
        expect(addOutputStub.secondCall.args[0]).to.equal('PACKAGE_INFO={"packageLabel":"artifact1","packagePath":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact1","uploadType":"type1","repoId":"repo1"}');

        expect(infoStub.callCount).to.equal(1);
        expect(infoStub.firstCall.args[0]).to.equal('Artifact download URL is: http://example.com/result');
    });

    it('should handle missing stepIdentifier environment variable', () => {
        delete process.env.stepIdentifier;

        const artifact = {
            bucketName: 'my-bucket',
            fileId: 'file1',
            artifactName: 'artifact1',
            fileMD5: 'md5hash',
            artifact: 'artifact1',
            uploadType: 'type1',
            repoId: 'repo1',
            fileParentId: 'parent1',
            artifactVersion: '1.0'
        } as UploadInputs;
        const result = {
            url: 'http://example.com/result'
        } as OSS.PutObjectResult;

        putParams(artifact, result);

        expect(addOutputStub.callCount).to.equal(3);
        expect(addOutputStub.firstCall.args[0]).to.equal('undefined.ARTIFACT={"ARTIFACT_URL":"http://example.com/artifact","ARTIFACT_NAME":"artifact1","ARTIFACT_MD5":"md5hash","WEB_DOWNLOAD_URL":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact1","artifact":"artifact1","type":"flowPublic","downloadUrl":"http://example.com/result","md5":"md5hash"}');
        expect(addOutputStub.secondCall.args[0]).to.equal('PACKAGE_INFO={"packageLabel":"artifact1","packagePath":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact1","uploadType":"type1","repoId":"repo1"}');

        expect(infoStub.callCount).to.equal(1);
        expect(infoStub.firstCall.args[0]).to.equal('Artifact download URL is: http://example.com/result');
    });

    it('should handle special characters in inputs', () => {
        const artifact = {
            bucketName: 'my-bucket',
            fileId: 'file1',
            artifactName: 'artifact&1',
            fileMD5: 'md5hash',
            artifact: 'artifact&1',
            uploadType: 'type&1',
            repoId: 'repo&1',
            fileParentId: 'parent&1',
            artifactVersion: '1.0'
        } as UploadInputs;
        const result = {
            url: 'http://example.com/result&1'
        } as OSS.PutObjectResult;

        putParams(artifact, result);

        expect(addOutputStub.callCount).to.equal(3);
        expect(addOutputStub.firstCall.args[0]).to.equal('step1.ARTIFACT={"ARTIFACT_URL":"http://example.com/artifact","ARTIFACT_NAME":"artifact&1","ARTIFACT_MD5":"md5hash","WEB_DOWNLOAD_URL":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact&1","artifact":"artifact&1","type":"flowPublic","downloadUrl":"http://example.com/result&1","md5":"md5hash"}');
        expect(addOutputStub.secondCall.args[0]).to.equal('PACKAGE_INFO={"packageLabel":"artifact&1","packagePath":"execution-component&bucketName=my-bucket&fileId=file1&artifactName=artifact&1","uploadType":"type&1","repoId":"repo&1"}');

        expect(infoStub.callCount).to.equal(1);
        expect(infoStub.firstCall.args[0]).to.equal('Artifact download URL is: http://example.com/result&1');
    });
});